#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <sys/ioctl.h>
#define EN_CTRL_C
#ifdef EN_CTRL_C
#include <signal.h>
#include <string.h>
#endif // EN_CTRL_C

#define DEV_PATH "/dev/pcie_cdev_ad"
#define BUFFER_SIZE (64 * 1024)
#define PRINT_BYTES 32
#define CHANNELS 16
#define SCALE_FACTOR_10V    0.000305f
#define SCALE_FACTOR_2V5    0.000076f
#define SCALE_FACTOR_5V     0.000152f

struct ad_range {
    uint8_t index;
    char str[8];
};
struct ad_val_t {
    uint8_t index;
    int32_t val;    // uV
};
// 与驱动一致的IOCTL命令定义（保持不变）
#define PCIE_CDEV_MAGIC 'P'
#define CMD_START_AD            _IO(PCIE_CDEV_MAGIC, 15)
#define CMD_STOP_AD             _IO(PCIE_CDEV_MAGIC, 16)
#define CMD_SET_SAMPLE          _IOW(PCIE_CDEV_MAGIC, 17, uint32_t)
#define CMD_SET_OSR             _IOW(PCIE_CDEV_MAGIC, 18, uint32_t)
#define CMD_SET_RANGE           _IOW(PCIE_CDEV_MAGIC, 19, struct ad_range)
#define CMD_GET_AD              _IOWR(PCIE_CDEV_MAGIC, 20, struct ad_val_t)

#ifdef EN_CTRL_C
volatile sig_atomic_t keep_running = 1;

// 信号处理函数
void handle_sigint(int sig) {
    if (sig == SIGINT) {
        printf("\n接收到 Ctrl+C 信号，程序将退出...\n");
        keep_running = 0;
    }
}
#endif // EN_CTRL_C

int main(int argc, char *argv[]) {
    int fd;
    uint8_t buffer[BUFFER_SIZE];
    ssize_t bytes_read;
    struct ad_range range[CHANNELS] = {
        {.index = 0, .str = "10"},
        {.index = 1, .str = "10"},
        {.index = 2, .str = "10"},
        {.index = 3, .str = "10"},
        {.index = 4, .str = "10"},
        {.index = 5, .str = "10"},
        {.index = 6, .str = "10"},
        {.index = 7, .str = "10"},
        {.index = 8, .str = "10"},
        {.index = 9, .str = "10"},
        {.index = 10, .str = "10"},
        {.index = 11, .str = "10"},
        {.index = 12, .str = "10"},
        {.index = 13, .str = "10"},
        {.index = 14, .str = "10"},
        {.index = 15, .str = "10"},
    };
    uint8_t i = 0;
    uint32_t val = 0;
    struct ad_val_t ad_val;
    uint16_t interval = 10;
    uint8_t channel = CHANNELS;
    char rang[8] = {'1', '0'};
#ifdef EN_CTRL_C
    struct sigaction sa;

    // 设置信号处理
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handle_sigint;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("设置信号处理器失败");
        exit(EXIT_FAILURE);
    }

    printf("按 Ctrl+C 可随时退出程序\n");
#endif // EN_CTRL_C

    if (2 == argc) {
        interval = (uint16_t)atoi(argv[1]);
    } else if (4 == argc) {
        interval = (uint16_t)atoi(argv[1]);
        channel = (uint8_t)atoi(argv[2]);
        memset(rang, 0, sizeof(rang));
        memcpy(rang, argv[3], strlen(argv[3]));
        if (0 != strncmp(rang, "10", strlen("10")) && 
            0 != strncmp(rang, "2.5", strlen("2.5")) && 
            0 != strncmp(rang, "5", strlen("5"))) {
            printf("range=%s error, must be 10 or 2.5 or 5\n", rang);
            return 0;
        }
    } else {
        printf("Please input'./%s interval channel range'\n", argv[0]);
        return 0;
    }

    // 打开设备文件
    fd = open(DEV_PATH, O_RDONLY);
    if (fd < 0) {
        perror("打开设备失败");
        exit(EXIT_FAILURE);
    }

    val = interval;
    if (ioctl(fd, CMD_SET_SAMPLE, &val) < 0) {
        perror("Set ad sample interval failed!");
        close(fd);
        return EXIT_FAILURE;
    }
    printf("Set ad sample interval success.\n");
    val = 0;
    if (ioctl(fd, CMD_SET_OSR, &val) < 0) {
        perror("Set OSR failed!");
        close(fd);
        return EXIT_FAILURE;
    }
    printf("Set ad OSR success.\n");
    if (CHANNELS <= channel) {
        for (i = 0; i < CHANNELS; i++) {
            memcpy(range[i].str, rang, sizeof(rang));
            if (ioctl(fd, CMD_SET_RANGE, &range[i]) < 0) {
                // perror("Set ad%d range failed!", i);
                fprintf(stderr, "Set ad%d range failed(%s)!\n", i, strerror(errno));
                close(fd);
                return EXIT_FAILURE;
            }
            printf("Set ad%d range%s success.\n", i, range[i].str);
        }
    } else {
        memcpy(range[channel].str, rang, sizeof(rang));
        if (ioctl(fd, CMD_SET_RANGE, &range[channel]) < 0) {
            // perror("Set ad%d range failed!", i);
            fprintf(stderr, "Set ad%d range failed(%s)!\n", channel, strerror(errno));
            close(fd);
            return EXIT_FAILURE;
        }
        printf("Set ad%d range%s success.\n", channel, range[channel].str);
    }

    // 开始 AD 采集
    if (ioctl(fd, CMD_START_AD) < 0) {
        perror("Start ad failed!");
        close(fd);
        return EXIT_FAILURE;
    }
    printf("Start ad success.\n");

    // 循环读取数据直到接收到Ctrl+C
    while (keep_running) {
        for (i = 0; i < CHANNELS; i++) {
            /* 单次读取通道值 */
            ad_val.index = i;
            if (ioctl(fd, CMD_GET_AD, &ad_val) < 0) {
                printf("Get AD%d value failed!\n", i);
            } else {
                printf("AD%d=%.6fV\n", ad_val.index, (1.0f * ad_val.val / 1000000.0f));
            }
        }
        // 读取数据
        bytes_read = read(fd, buffer, BUFFER_SIZE);
        if (bytes_read < 0) {
            if (errno == EINTR && !keep_running) {
                // 被信号中断且是退出信号
                break;
            }
            perror("读取错误");
            close(fd);
            exit(EXIT_FAILURE);
        } else if (bytes_read < BUFFER_SIZE) {
            fprintf(stderr, "警告: 期望 %d 字节, 实际 %zd 字节\n", 
                    BUFFER_SIZE, bytes_read);
            // 继续处理已读取的部分数据
        }

        // memcpy(&val, &buffer[10], sizeof(val)); 
        // printf("daq_acquire=%d\n", val);
        // 打印前32字节
        printf("\n读取到 %zd 字节数据:\n", bytes_read);
        printf("前32字节原始数据:\n");
        for (int i = 0; i < PRINT_BYTES && i < bytes_read; i++) {
            printf("字节 %02d: 0x%02X\n", i, buffer[i]);
        }

        // 检查是否有足够数据用于通道转换
        if (bytes_read < PRINT_BYTES + 2 * CHANNELS) {
            fprintf(stderr, "错误: 数据不足，无法解析通道数据\n");
            continue;
        }

        // 处理AD通道数据
        printf("\nAD通道数据（转换后）:\n");
        // for (int offset = PRINT_BYTES; offset <= (PRINT_BYTES + 2 * CHANNELS); offset += 2 * CHANNELS) {
        for (int offset = PRINT_BYTES; offset < bytes_read; offset += 2 * CHANNELS) {
            // 检查剩余数据是否足够
            if (offset + 2 * CHANNELS > bytes_read) {
                fprintf(stderr, "警告: 数据块不完整，跳过剩余部分\n");
                break;
            }
            
            printf("--- 数据块 %d ---\n", (offset - PRINT_BYTES) / (2 * CHANNELS) + 1);
            // for (int cha = 0; cha < CHANNELS; cha++) {
            //     int i = offset + cha * 2;
            //     // 组合两个字节为16位数据（小端模式）
            //     int16_t raw = ((int16_t)buffer[i + 1] << 8) | buffer[i];
            //     if (raw > 0x2FFF) {
            //         printf("--- 数据块 %d ---\n", (offset - PRINT_BYTES) / (2 * CHANNELS) + 1);
            //         for (int ch = 0; ch < CHANNELS; ch++) {
            //             int idx = offset + ch * 2;
            //             // 组合两个字节为16位数据（小端模式）
            //             uint16_t raw_value = ((uint16_t)buffer[idx + 1] << 8) | buffer[idx];
                        
            //             // 应用转换公式
            //             float result = raw_value * SCALE_FACTOR_10V;
            //             if (0 == strncmp(range[ch].str, "10", strlen("10"))) {
            //                 result = raw_value * SCALE_FACTOR_10V;
            //             } else if (0 == strncmp(range[ch].str, "2.5", strlen("2.5"))) {
            //                 result = raw_value * SCALE_FACTOR_2V5;
            //             } else if (0 == strncmp(range[ch].str, "5", strlen("5"))) {
            //                 result = raw_value * SCALE_FACTOR_5V;
            //             }
            //             printf("通道 %02d: 原始值=0x%04X (%5u) -> %.6fV\n", 
            //                 ch, raw_value, raw_value, result);
            //         }
            //     }
            // }

            for (int ch = 0; ch < CHANNELS; ch++) {
                int idx = offset + ch * 2;
                // 组合两个字节为16位数据（小端模式）
                int16_t raw_value = ((int16_t)buffer[idx + 1] << 8) | buffer[idx];
                
                // 应用转换公式
                float result = raw_value * SCALE_FACTOR_10V;
                if (0 == strncmp(range[ch].str, "10", strlen("10"))) {
                    result = raw_value * SCALE_FACTOR_10V;
                } else if (0 == strncmp(range[ch].str, "2.5", strlen("2.5"))) {
                    result = raw_value * SCALE_FACTOR_2V5;
                } else if (0 == strncmp(range[ch].str, "5", strlen("5"))) {
                    result = raw_value * SCALE_FACTOR_5V;
                }
                printf("通道 %02d: 原始值=0x%04X (%5u) -> %.6fV\n", 
                    ch, raw_value, raw_value, result);
            }
        }
        
        // 添加短暂延迟以便观察输出
        printf("\n等待新数据...\n");
        usleep(1); // 0.5秒延迟
    }

    printf("Stop ad...\n");
    // 停止 AD 采集
    if (ioctl(fd, CMD_STOP_AD) < 0) {
        perror("Stop ad failed!");
        close(fd);
        return EXIT_FAILURE;
    }
    printf("Stop ad success.\n");

    // 清理资源
    close(fd);
    printf("设备已关闭，程序退出\n");
    return 0;
}
